using System;
using dnAnalytics.Statistics.Distributions;
using NUnit.Framework;

namespace dnAnalytics.Tests.Statistics.Distributions
{
    [TestFixture]
    public class NegativeBinomialTests
    {
        private const double mAcceptableError = 1e-12;

        [Test]
        public void IntegerR()
        {
            NegativeBinomial nb = new NegativeBinomial(10, 0.3);

            Assert.AreEqual(10.0, nb.R, mAcceptableError);
            Assert.AreEqual(0.3, nb.P, mAcceptableError);
            Assert.AreEqual(23.3333333333333333, nb.Mean, mAcceptableError);
            Assert.AreEqual(8.8191710368819700, nb.StdDev, mAcceptableError);
            Assert.AreEqual(77.7777777777778000, nb.Variance, mAcceptableError);
            Assert.AreEqual(21, nb.Mode, mAcceptableError);

            Assert.AreEqual(0.0000059049000000, nb.Probability(0), mAcceptableError);
            Assert.AreEqual(0.0000413343000000, nb.Probability(1), mAcceptableError);
            Assert.AreEqual(1.591370549999998e-04, nb.Probability(2), mAcceptableError);
            Assert.AreEqual(4.455837540000012e-04, nb.Probability(3), mAcceptableError);
            Assert.AreEqual(0.001013703040350, nb.Probability(4), mAcceptableError);
            Assert.AreEqual(0.015408540450042, nb.Probability(10), mAcceptableError);
            Assert.AreEqual(0.047187233687333, nb.Probability(20), mAcceptableError);
            Assert.AreEqual(0.028204325403718, nb.Probability(30), mAcceptableError);
            Assert.AreEqual(8.142819739009949e-09, nb.Probability(100), mAcceptableError);
            Assert.AreEqual(2.132903391450372e-139, nb.Probability(1000), mAcceptableError);
        }

        [TestCase(15.0, 1.3, ExpectedException = typeof(ArgumentOutOfRangeException))]
        [TestCase(-1.0, 0.3, ExpectedException = typeof(ArgumentOutOfRangeException))]
        public void InvalidParams(double a, double b)
        {
            var nb = new NegativeBinomial(a, b);
        }

        [Test]
        public void GetSetRNG()
        {
            NegativeBinomial nb = new NegativeBinomial(10, 0.3);

            // Try getting the random number generator.
            System.Random rnd = nb.RandomNumberGenerator;
            // Try setting the random number generator.
            nb.RandomNumberGenerator = new System.Random();
        }
    }
}